#!/usr/bin/env python
#
#       Maps.py
#       
#       Copyright 2009 Ben Davis <its.hip@gmail.com>, Pete Lord <mr.petelord@gmail.com>
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import os
import pygame

import Options

from Client import Client
client = Client()

class Tile():
    def __init__(self, x, y, cloud, smoke, texture_path):        
        self.x = x
        self.y = y
        self.cloud = cloud # do we have cloud here? DEFAULT: False
        self.smoke = smoke # do we have smoke here? DEFAULT: False
        self.textures = client.tile_graphics[texture_path]
        
class Map():
    def __setup__(self):
        temp = os.path.join('Data', 'Tiles')
        self.texture_list = [os.path.join(temp, 'Nothing'),
                             os.path.join(temp, 'Cloud1'),
                             os.path.join(temp, 'Cloud2'),
                             os.path.join(temp, 'Cloud3'),
                             os.path.join(temp, 'Cloud4')
                            ]
        i = 0
        self.tiles = []
        for item in self.data:
            if i % self.width == 0:
                self.tiles.append([])
            self.tiles[-1].append(Tile(i % self.width, i / self.width, False, False, self.texture_list[item]))
            i += 1
        self.update_surfaces()
    
    def update_surfaces(self):
        # Draw ground tiles
        self.surfaces = []
        for zoom_level in (0, 1, 2):
            # Create a new surface of the correct width and height for the zoom level
            self.surfaces.append(pygame.Surface((Options.TILE_WIDTH[zoom_level] * 0.5 * (self.width + self.height),\
                                       Options.TILE_HEIGHT[zoom_level] * 0.5 * (self.width + self.height))))
            # Loop through each tile
            for j in range(self.height):
                for i in range(self.width):
                    # Calculate the screen (x, y)
                    x = (i - j + self.height - 1) * 0.5 * Options.TILE_WIDTH[zoom_level]
                    y = (i + j) * 0.5 * Options.TILE_HEIGHT[zoom_level]
                    # Draw the tile to surface
                    self.surfaces[-1].blit(self.tiles[j][i].textures[zoom_level], (x, y))
            self.surfaces[-1].convert()
                 
    def draw(self):
        client.game.surface.blit(self.surfaces[Options.ZOOM_LEVEL], (0, 0), client.game.rect)

    def map_location(self, pos):
        """ Accepts absolute (x, y) and returns map (x, y) """
        x, y = pos
        # Take screen offset out of (x, y)
        #x, y = x + client.game.rect.x, y + client.game.rect.y
        
        # Account for map (0, 0) not centred at (0, 0) on screen
        x, y = x - self.height * Options.TILE_WIDTH[Options.ZOOM_LEVEL] / 2, y - Options.TILE_HEIGHT[Options.ZOOM_LEVEL] / 2
        
        # Convert screen (x, y) to map (x, y)
        # Note: it does the calculation as floats for accuracy,
        # then adds 0.5 to counter the rounding up/down issue
        map_x = int(float(y) / Options.TILE_HEIGHT[Options.ZOOM_LEVEL] + float(x) / Options.TILE_WIDTH[Options.ZOOM_LEVEL] + 0.5)
        map_y = int(float(y) / Options.TILE_HEIGHT[Options.ZOOM_LEVEL] - float(x) / Options.TILE_WIDTH[Options.ZOOM_LEVEL] + 0.5)
        return map_x, map_y
    
    def get_at_xy(self, pos):
        """ Accepts map (x, y) and returns object currently there.
        
        If no object there, return None"""
        for player in client.game.players.values():
            for ship in player.ships.values():
                if (ship.x, ship.y) == pos:
                    return ship
        return None
        
    def get_at_screen_xy(self, pos):
        """ Accepts screen (x, y) and returns object currently there.
        
        If no object there, return None"""
        return self.get_at_xy(self.map_location(pos))
